﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.IO;

namespace ASPMVC
{
    public class ParseProcess
    {
        string path_file;
        Project project = new Project();
        Hashtable hash_controller = new Hashtable();
        Hashtable hash_scaffold = new Hashtable();
        Hashtable hash_model = new Hashtable();

        public ParseProcess()
        {

        }

        public bool validateNameFile(String path_file)
        {
            this.path_file = path_file;
            Match match_path_file = Regex.Match(path_file, @"([A-Za-z0-9\-]+)\.agile$", RegexOptions.IgnoreCase);
            if (match_path_file.Success)
            {
                return true;
            }
            return false;
        }

        public void processFile()
        {            
            string[] lines_file = System.IO.File.ReadAllLines(this.path_file);
            Regex regex_line_file = new Regex(@"(^Application\.|^Scaffold\.|^Controller\.|^Model\.)(.*?)");
            foreach (string line in lines_file)
            {
                Match match_home_file = regex_line_file.Match(line);
                if (match_home_file.Success)
                {
                    if (match_home_file.Value.Equals("Application."))
                    {
                        processApplication(line);
                    }
                    if (match_home_file.Value.Equals("Controller."))
                    {
                        processController(line);
                    }
                    if (match_home_file.Value.Equals("Scaffold."))
                    {
                        processScaffold(line);
                    }
                    if (match_home_file.Value.Equals("Model."))
                    {
                        processModel(line);
                    }
                }
            }

            List<Controller> controllers = new List<Controller>();
            IDictionaryEnumerator en = hash_controller.GetEnumerator();
            while (en.MoveNext())
            {
                string str = en.Key.ToString();
                controllers.Add((Controller)hash_controller[str]);
            }
            project.controllers = controllers;

            List<Scaffold> scaffolds = new List<Scaffold>();
            IDictionaryEnumerator es = hash_scaffold.GetEnumerator();
            while (es.MoveNext())
            {
                string str = es.Key.ToString();
                scaffolds.Add((Scaffold)hash_scaffold[str]);
            }
            project.scaffolds = scaffolds;

            List<Model> models = new List<Model>();
            IDictionaryEnumerator em = hash_model.GetEnumerator();
            while (em.MoveNext())
            {
                string str = em.Key.ToString();
                models.Add((Model)hash_model[str]);
            }
            project.models = models;


            SerializeToXML();            
        }

        private void processApplication(String line)
        {
            Application app = new Application();
            //Console.WriteLine(line);
            //Console.WriteLine(match_home_file.Value);
            Match match_app = Regex.Match(line, @"(Application)[.]{1}(config)[.]{1}(define)(\(.*\))", RegexOptions.IgnoreCase);
            if (match_app.Success)
            {
                string type_class = match_app.Groups[1].Value;
                string name_class = match_app.Groups[2].Value;
                string type_function = match_app.Groups[3].Value;
                string value_function = match_app.Groups[4].Value;

                //Console.WriteLine("type_class : " + type_class);
                //Console.WriteLine("name_class : " + name_class);
                //Console.WriteLine("type_function : " + type_function);
                //Console.WriteLine("value_function : " + value_function);

                string pat = "(\\w+)[=][\"](.*?)[\"]";
                Regex r = new Regex(pat, RegexOptions.IgnoreCase);

                Match m = r.Match(value_function);
                while (m.Success)
                {
                    if (m.Groups[1].Value.Equals("name"))
                    {
                        app.name = m.Groups[2].Value;
                    }
                    if (m.Groups[1].Value.Equals("author"))
                    {
                        app.author = m.Groups[2].Value;
                    }
                    if (m.Groups[1].Value.Equals("description"))
                    {
                        app.description = m.Groups[2].Value;
                    }
                    if (m.Groups[1].Value.Equals("version"))
                    {
                        app.version = m.Groups[2].Value;
                    }
                    m = m.NextMatch();
                }
                project.application = app;
            }

        }

        private void processController(String line)
        {
            Match match_app = Regex.Match(line, @"(Controller)[.]{1}(.*?)[.]{1}(.*?)(\(.*\))", RegexOptions.IgnoreCase);
            if (match_app.Success)
            {
                Controller controller;
                string type_class = match_app.Groups[1].Value;
                string name_class = match_app.Groups[2].Value;
                string type_function = match_app.Groups[3].Value;
                string value_function = match_app.Groups[4].Value;

                if (hash_controller.ContainsKey(name_class))
                {
                    controller = (Controller)hash_controller[name_class];
                }
                else
                {
                    controller = new Controller();
                    controller.name = name_class;
                    hash_controller.Add(controller.name, controller);
                }

                string pat = "(\\w+)[=][\"](.*?)[\"]";
                Regex r = new Regex(pat, RegexOptions.IgnoreCase);
                Match m = r.Match(value_function);

                if (type_function.Equals("define"))
                {
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            controller.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                }
                if (type_function.Equals("addAttribute"))
                {
                    Attribute attribute = new Attribute();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            attribute.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("type"))
                        {
                            attribute.type = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("notnull"))
                        {
                            attribute.notnull = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            attribute.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    controller.attributes.Add(attribute);
                }
                if (type_function.Equals("addFunction"))
                {
                    Function function = new Function();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            function.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("title"))
                        {
                            function.title = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            function.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    controller.functions.Add(function);
                }
                if (type_function.Equals("addView"))
                {
                    View view = new View();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            view.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("title"))
                        {
                            view.title = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            view.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    controller.views.Add(view);
                }

            }                    
        }

        private void processScaffold(String line)
        {
            Match match_app = Regex.Match(line, @"(Scaffold)[.]{1}(.*?)[.]{1}(.*?)(\(.*\))", RegexOptions.IgnoreCase);
            if (match_app.Success)
            {
                Scaffold scaffold;
                string type_class = match_app.Groups[1].Value;
                string name_class = match_app.Groups[2].Value;
                string type_function = match_app.Groups[3].Value;
                string value_function = match_app.Groups[4].Value;

                if (hash_scaffold.ContainsKey(name_class))
                {
                    scaffold = (Scaffold)hash_scaffold[name_class];
                }
                else
                {
                    scaffold = new Scaffold();
                    scaffold.name = name_class;
                    hash_scaffold.Add(scaffold.name, scaffold);
                }

                string pat = "(\\w+)[=][\"](.*?)[\"]";
                Regex r = new Regex(pat, RegexOptions.IgnoreCase);
                Match m = r.Match(value_function);

                if (type_function.Equals("define"))
                {
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            scaffold.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                }
                if (type_function.Equals("addAttribute"))
                {
                    Attribute attribute = new Attribute();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            attribute.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("type"))
                        {
                            attribute.type = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("notnull"))
                        {
                            attribute.notnull = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            attribute.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    scaffold.attributes.Add(attribute);
                }
                if (type_function.Equals("addFunction"))
                {
                    Function function = new Function();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            function.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("title"))
                        {
                            function.title = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            function.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    scaffold.functions.Add(function);
                }
                if (type_function.Equals("addView"))
                {
                    View view = new View();
                    while (m.Success)
                    {
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            view.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("title"))
                        {
                            view.title = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            view.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    scaffold.views.Add(view);
                }
            }
        }

        private void processModel(String line)
        {
            Match match_app = Regex.Match(line, @"(Model)[.]{1}(.*?)[.]{1}(.*?)(\(.*\))", RegexOptions.IgnoreCase);
            if (match_app.Success)
            {
                Model model;
                string type_class = match_app.Groups[1].Value;
                string name_class = match_app.Groups[2].Value;
                string type_function = match_app.Groups[3].Value;
                string value_function = match_app.Groups[4].Value;

                if (hash_model.ContainsKey(name_class))
                {
                    model = (Model)hash_model[name_class];
                }
                else
                {
                    model = new Model();
                    model.name = name_class;
                    hash_model.Add(model.name, model);
                }

                string pat = "(\\w+)[=][\"](.*?)[\"]";
                Regex r = new Regex(pat, RegexOptions.IgnoreCase);
                Match m = r.Match(value_function);

                if (type_function.Equals("define"))
                {
                    while (m.Success)
                    {                        
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            model.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                }
                if (type_function.Equals("addAttribute"))
                {
                    Attribute attribute = new Attribute();
                    while (m.Success)
                    {                        
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            attribute.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("type"))
                        {
                            attribute.type = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("notnull"))
                        {
                            attribute.notnull = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            attribute.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    model.attributes.Add(attribute);
                }
                if (type_function.Equals("addFunction"))
                {
                    Function function = new Function();
                    while (m.Success)
                    {                        
                        if (m.Groups[1].Value.Equals("name"))
                        {
                            function.name = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("title"))
                        {
                            function.title = m.Groups[2].Value;
                        }
                        if (m.Groups[1].Value.Equals("description"))
                        {
                            function.description = m.Groups[2].Value;
                        }
                        m = m.NextMatch();
                    }
                    model.functions.Add(function);
                }                
            }
        }
        
        private void SerializeToXML()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Project));
            TextWriter textWriter = new StreamWriter(@"D:\agile4gl\1.0v\src\al-plugin-asp.net-mvc\meta.xml");
            serializer.Serialize(textWriter, project);
            textWriter.Close();
        }
    }
}
